# 函数在开发过程中，可以更高效的实现代码重用
# 函数就是讲一段具有独立功能的代码块整合到一个整体并命名，在调用时声明名称就好
# 函数定义——def 函数名（参数）：
# 调用函数——函数名（参数）
# 函数先定义后使用 参数可有可无

# 两个参数求和
def sum_add(a, b):
    return a + b


result1 = sum_add(10, 30)
result2 = sum_add(60, 30)
print(result1, result2)


# 函数的说明文档/函数的文档说明
def sum_sub(a, b):
    """求差函数"""
    return a - b


# 函数嵌套 函数执行顺序
# 如果函数1中，调用了另一个函数2，那么先把函数2执行完后，才会返回到原函数1的位置继续执行

# 打印图案
def print_line():
    print('_' * 20)


def print_lines(num):
    i = 0
    while i < num:
        print_line()
        i += 1


print_lines(5)


# 求三个数平均值
def sum_num(a, b, c):
    return a + b + c


def average_num(a, b, c):
    sum_result = sum_num(a, b, c)
    return sum_result / 3


result = average_num(1, 2, 3)
print(result)

# 局部变量和全局变量
# 局部变量：定义在函数体内部的变量，即只在函数体内部生效 在函数体内部临时保存数据，函数调用完成后，即销毁局部变量
# 全局变量：函数体内外都能生效的变量
a = 100


def test_a():
    print(a)


def test_b():
    global a
    a = 200
    print(a)


test_a()
test_b()
print(a)


# 返回值作为参数传递
# 函数的返回值
def return_num():
    return 1
    return 2


print(return_num())


# return a，b 写法，返回多个数据的时候，默认是元组类型
# return后面可以连接列表、元组或字典，以返回多个值

# 位置参数：形参和实参的个数和书写顺序必须一致
# 关键字参数：key=value 形参和实参的书写顺序可以不一样，关键字参数必须在位置参数的后面
# 缺省函数：即默认参数，key=value
# 不定长位置参数：收集所有位置参数，返回一个元组（包裹位置传递，组包过程）
# 不定长关键字参数：收集所有关键字参数，返回一个元组（包裹关键字传递，组包过程）

# python中，数据的传递都是通过引用
# 拆包：元组、字典
def return_num():
    return 100, 200


num1, num2 = return_num()
print(num1)
print(num2)

# 字典拆包
dict1 = {'name': 'TOM', 'age': 18}
a, b = dict1
# 对字典进行拆包，取出来的是字典的key
print(a)
print(b)
print(dict1[a])
print(dict1[b])

# 数据交换
a = 10
b = 20
c = 0
c = a
a = b
b = c
print(a, b)

a, b = 10, 20
a, b = b, a
print(a, b)


# 递归
# 数字累加和
def sum_numbers(num):
    if num == 1:
        return 1
    result3 = num + sum_numbers(num - 1)

    return result3


sum_result = sum_numbers(20)
print(sum_result)


# lambda表达式
# lambda实现
print((lambda a, b: a + b)(1, 2))

# lambda参数形式
# 无参数
print((lambda: 100)())
# 一个参数
print((lambda a: a)('hello world'))
# 默认参数
print((lambda a, b, c=100: a+b+c)(10, 20))
# 可变参数 *args
print((lambda *args: args)(10, 20, 30))
# 这里的可变参数传入到lambda之后，返回值为元组
# 可变参数 **kwargs
print((lambda **kwargs: kwargs)(name='python', age=20))

fn2 = lambda: 100
print(fn2)
print(fn2())
# 直接打印lambda表达式，输出的是此lambda的内存地址




